package com.skyable.auth.config.security.handler;

import com.alibaba.fastjson.JSONObject;
import com.skyable.auth.entity.SysPermission;
import com.skyable.auth.entity.SysUser;
import com.skyable.auth.service.IPermissionService;
import com.skyable.auth.service.IUserService;
import com.skyable.auth.utils.RedisUtil;
import com.skyable.common.common.ResponseResult;
import com.skyable.common.common.ServiceResult;
import com.skyable.common.constants.param.CommonParams;
import com.skyable.common.constants.redis.RedisKeyConstants;
import com.skyable.common.constants.redis.RedisTimeoutConstants;
import com.skyable.common.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author GaoYuan
 * @date 2019/11/4 16:30
 * @desc 登录成功处理器
 */
@Slf4j
@Component
public class CloudAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{

    @Autowired
    private IUserService userService;
    @Autowired
    private IPermissionService permissionService;

    private RequestCache requestCache = new HttpSessionRequestCache();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        SavedRequest savedRequest = requestCache.getRequest(request, response);
        User principal = (User) authentication.getPrincipal();
        String username = principal.getUsername();
        log.info("web user " + username + " authenticate success");
        SysUser sysUser = saveUserInfo(username);

        if(savedRequest == null) {
            Map<String,Object> params = new HashMap<>(2);
            if(sysUser != null) {
                params.put(CommonParams.HEADER_USER_ID, sysUser.getId());
                params.put(CommonParams.HEADER_USER_DOMAIN_ID, sysUser.getDomainId());
            }
            //可以传map存放其他信息
            String token = JwtTokenUtil.generateToken(username, params);
            response.getWriter().write(JSONObject.toJSONString(ResponseResult.success(token)));
            response.getWriter().flush();
        } else {
            //参照SavedRequestAwareAuthenticationSuccessHandler类方法
            String targetUrlParameter = getTargetUrlParameter();
            if (isAlwaysUseDefaultTargetUrl()
                    || (targetUrlParameter != null && StringUtils.hasText(request
                    .getParameter(targetUrlParameter)))) {
                requestCache.removeRequest(request, response);
                super.onAuthenticationSuccess(request, response, authentication);

                return;
            }

            clearAuthenticationAttributes(request);

            // Use the DefaultSavedRequest URL
            String targetUrl = savedRequest.getRedirectUrl();
            System.out.println("targetUrl:" + targetUrl);
            log.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
            getRedirectStrategy().sendRedirect(request, response, targetUrl);
        }
    }

    /**
     * 缓存用户信息
     * @param username
     */
    private SysUser saveUserInfo(String username) {
        ServiceResult<SysUser> serviceResult = userService.getUserByUserName(username);
        //token缓存30分钟
        SysUser sysUser = serviceResult.getResult();
        if(sysUser == null) {
            return null;
        }

        ServiceResult<List<SysPermission>> listServiceResult = permissionService.findPermissionByUserName(username);
        if(listServiceResult.getSuccess()) {
            List<SysPermission> sysPermissionList = listServiceResult.getResult();
            if(sysPermissionList != null && !sysPermissionList.isEmpty()) {
                List<String> permissionCodeList = new ArrayList<>();
                for(SysPermission sysPermission : sysPermissionList) {
                    permissionCodeList.add(sysPermission.getCreateUser());
                }
                sysUser.setPermissionCodeList(permissionCodeList);
            }
        }
        RedisUtil.setEx(RedisKeyConstants.WEB_USER_INFO_KEY + username, JSONObject.toJSONString(sysUser), RedisTimeoutConstants.USER_INFO_TIME_OUT, TimeUnit.SECONDS);
        return sysUser;
    }
}